package com.example.week9_spring_aop.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

@Aspect
@Component
public class TestAspect {

    Map<String, ApiInfo> apiInfoMap = new HashMap<>();

    @Around("execution(* com.example.week9_spring_aop.apis.impl.ApiForTestImpl.TestApi(..))")
    public Object Monitor(ProceedingJoinPoint joinPoint) {

        String methodName = joinPoint.getSignature().getName();
        ApiInfo apiInfo = apiInfoMap.get(methodName);
        if (apiInfo == null) {
            apiInfo = new ApiInfo();
            apiInfoMap.put(methodName, apiInfo);
        }
        apiInfo.count++;
        long startTime = System.currentTimeMillis();
        Object res = null;
        try {
            res = joinPoint.proceed();
        } catch (Throwable throwable) {
            long endTime = System.currentTimeMillis();
            long time = endTime - startTime;
            apiInfo.totalTime += time;
            apiInfo.maxTime = Math.max(apiInfo.maxTime, time);
            apiInfo.minTime = Math.min(apiInfo.minTime, time);
            apiInfo.avgTime = apiInfo.totalTime / apiInfo.count;
            apiInfo.exceptionCount++;
            return res;
        }
        long endTime = System.currentTimeMillis();
        long time = endTime - startTime;
        apiInfo.totalTime += time;
        apiInfo.maxTime = Math.max(apiInfo.maxTime, time);
        apiInfo.minTime = Math.min(apiInfo.minTime, time);
        apiInfo.avgTime = apiInfo.totalTime / apiInfo.count;
        return res;
    }

    public void printApiInfo() {
        for (Map.Entry<String, ApiInfo> entry : apiInfoMap.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }

}

